package com.kedacom.demo.sigar;

import java.util.ArrayList;
import java.util.List;

import org.hyperic.sigar.MultiProcCpu;
import org.hyperic.sigar.ProcCpu;
import org.hyperic.sigar.ProcMem;
import org.hyperic.sigar.ProcState;
import org.hyperic.sigar.Sigar;
import org.hyperic.sigar.SigarException;
import org.hyperic.sigar.ptql.ProcessFinder;

public class ProcessMonitor {

    /**
     * ***********
     * Executes a SIGAR PTQL query, returning the PIDs of the processes that
     * match the query. For more info on SIGAR's PTQL - Process Table Query
     * Language, see: http://support.hyperic.com/display/SIGAR/PTQL
     *
     * @param query the PTQL query.
     * @return the pids.
     * @throws SigarException in case of an error.
     */
    public static List<Long> getPidsWithQuery(Sigar sigar, final String query)
            throws SigarException {
        final ProcessFinder finder = new ProcessFinder(sigar);

        final long[] results = finder.find(query);
        final List<Long> list = new ArrayList<Long>(results.length);
        for (final long result : results) {
            list.add(result);
        }

        return list;

    }

    /**
     * *******
     * Returns the pids of Java processes where the name specified in in the
     * process arguments. This will usually be the java process' main class,
     * though that may not always be the case.
     *
     * PTQL Query: "State.Name.eq=java,Args.*.eq=" + name
     *
     * @param name the java main class or jar file name.
     * @return the pids that match the query, may be zero, one or more.
     * @throws SigarException in case of an error.
     */
    public static List<Long> getPidsWithMainClass(Sigar sigar, final String name)
            throws SigarException {
        return getPidsWithQuery(sigar, "State.Name.eq=java,Args.*.eq=" + name);
    }

    /**
     * ***********
     * Returns the pids of processes where the base name of the process
     * executable is as specified. PTQL Query: "State.Name.eq=" + name
     *
     * @param name the process name.
     * @return the matching PIDs.
     * @throws SigarException in case of an error.
     */
    public static List<Long> getPidsWithName(Sigar sigar, final String name)
            throws SigarException {
        return getPidsWithQuery(sigar, "State.Name.eq=" + name);
    }

    public static long getPidWithServiceName(Sigar sigar, final String serviceName) {
        long pid = -1;
        try {
            pid = sigar.getServicePid(serviceName);
        }
        catch (SigarException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return pid;
    }

    /**
     * ***********
     * Returns the pids of processes where the full name of the process
     * executable is as specified. PTQL Query: "Exe.Name.eq=" + name.
     *
     * @param name the process name.
     * @return the matching PIDs.
     * @throws SigarException in case of an error.
     */
    public static List<Long> getPidsWithFullName(Sigar sigar, final String name)
            throws SigarException {
        return getPidsWithQuery(sigar, "Exe.Name.eq=" + name);
    }

    public void getMultiProcByPTQL(Sigar sigar, String PTQL) {
        MultiProcCpu MPC = null;
        try {
            MPC = sigar.getMultiProcCpu(PTQL);
            System.out.println("getMultiProcCpu:" + MPC);
            ProcMem PM = sigar.getMultiProcMem(PTQL);
            System.out.println("getMultiProcMem:" + PM);

        }
        catch (SigarException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    public void getMultiProcByPort(Sigar sigar, String protocol, String port) {
        long pid = -1;
        try {
            pid = sigar.getProcPort(protocol, port);
            this.getProcessInfoByPid(sigar, pid);
        }
        catch (SigarException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    public void getMultiProcByPort(Sigar sigar, int protocol, long port) {
        long pid = -1;
        try {
            pid = sigar.getProcPort(protocol, port);
            this.getProcessInfoByPid(sigar, pid);
        }
        catch (SigarException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    public void getProcessInfoByServiceName(Sigar sigar, String serviceName) {
        long pid = -1;
        try {
            pid = sigar.getServicePid(serviceName);
        }
        catch (SigarException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        getProcessInfoByPid(sigar, pid);
    }

    //获取所有进程的相关信息
    public final void getAllProcessInfo(Sigar sigar) {
        long[] pids = null;
        try {
            pids = sigar.getProcList();
        }
        catch (SigarException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        for (long pid : pids) {
            getProcessInfoByPid(sigar, pid);
        }
    }

    public final void getProcessInfoByPid(Sigar sigar, long pid) {
        ProcState prs = null;
        System.out.println(pid + "进程状态-->");
        try {
            prs = sigar.getProcState(pid);
            System.out.print("进程名称：" + prs.getName() + ",");
            switch (prs.getState()) {
                case ProcState.IDLE:
                    System.out.print("进程状态：空闲" + ",");
                    break;
                case ProcState.RUN:
                    System.out.print("进程状态：运行中" + ",");
                    break;
                case ProcState.SLEEP:
                    System.out.print("进程状态：休眠" + ",");
                    break;
                case ProcState.STOP:
                    System.out.print("进程状态：停止" + ",");
                    break;
                case ProcState.ZOMBIE:
                    System.out.print("进程状态：僵尸" + ",");
                    break;
            }
            System.out.print("父进程：" + prs.getPpid() + ",");
            System.out.print("终端号：" + prs.getTty() + ",");
            System.out.print("Nice：" + prs.getNice() + ",");
            System.out.print("优先级：" + prs.getPriority() + ",");
            System.out.print("线程数：" + prs.getThreads() + ",");
            System.out.println("处理器：" + prs.getProcessor());

        }
        catch (SigarException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        //进程CPU
        ProcCpu pCpu = new ProcCpu();
        try {
            //pCpu = sigar.getProcCpu(pid);
            pCpu.gather(sigar, pid);
        }
        catch (SigarException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.print("进程CPU:");
        System.out.print(pCpu.getPercent() * 100D + " %,");
        System.out.print("LastTime：" + pCpu.getLastTime() + ",");
        System.out.print("StartTime：" + pCpu.getStartTime() + ",");
        System.out.print("UserCpuTime：" + pCpu.getUser() + " jiffies,");
        System.out.print("SysCpuTime：" + pCpu.getSys() + " jiffies,");
        System.out.println("TotalCpuTime：" + pCpu.getTotal() + " jiffies");

        //进程内存
        ProcMem procMem = null;
        try {
            procMem = sigar.getProcMem(pid);
        }
        catch (SigarException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.print("进程Mem:");
        System.out.print(procMem.getSize() / 1024 / 1024 + "M,");
        System.out.print("常驻内存：" + procMem.getResident() / 1024 / 1024 + "M,");
        System.out.print("共享内存：" + procMem.getShare() + ",");
        System.out.print("次要页错误：" + procMem.getMinorFaults() + " ,");
        System.out.print("主要页错误：" + procMem.getMajorFaults() + " ,");
        System.out.println("页面错误：" + procMem.getPageFaults() + " ");

        try {
            System.out.println("getProcCredName:" + sigar.getProcCredName(pid));
            System.out.println("getProcEnv:" + sigar.getProcEnv(pid));
            System.out.println("getProcFd:" + sigar.getProcFd(pid));
            System.out.println("getProcModules:" + sigar.getProcModules(pid));
            System.out.println("getProcTime:" + sigar.getProcTime(pid));
        }
        catch (SigarException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

    /**
     * @param args
     */
    public static void main(String[] args) {
        Sigar sigar = new Sigar();
        ProcessMonitor pm = new ProcessMonitor();
        //pm.getProcessInfoByPid(sigar, sigar.getPid());
        //pm.getAllProcessInfo(sigar);
        //pm.getProcessInfoByServiceName(sigar, "MySQL");
        //PTQL-https://support.hyperic.com/display/SIGAR/PTQL
        //pm.getMultiProcByPTQL(sigar, "State.Name.re=mysqld");	//匹配
        pm.getMultiProcByPTQL(sigar, "State.Name.eq=mysqld");	//等于
        //pm.getMultiProcByPort(sigar, NetFlags.CONN_TCP, 3306);


        /*ProcessMonitor pm = new ProcessMonitor();
         List<ProcessInfo> processInfos = pm.getProcessInfo();
         for(ProcessInfo pi :processInfos){
         System.out.println(pi);
         }*/

        /*while (true) {
         try {
         Thread.sleep(1000);
         List<ProcessInfo> processInfos = pm.getProcessInfo();
         for(ProcessInfo pi :processInfos){
         System.out.println(pi);
         }


         } catch (InterruptedException e) {

         e.printStackTrace();
         }
         }*/

    }
}
